package com.atguigu.gmall.cart.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.cart.mapper.CartInfoMapper;
import com.atguigu.gmall.cart.service.CartAsyncService;
import com.atguigu.gmall.cart.service.CartService;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.product.SkuInfo;
import com.atguigu.gmall.product.feign.ProductFeignClient;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.ParameterResolutionDelegate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.function.Supplier;
import java.util.stream.Collectors;

@Transactional(rollbackFor = Exception.class)
@Service
public class CartServiceImpl implements CartService {

    @Autowired
    private CartInfoMapper cartInfoMapper;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private ProductFeignClient productFeignClient;
    @Autowired
    private CartAsyncService cartAsyncService;
    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;

    /**
     * 新增购物车
     *
     * @param skuId
     * @param num
     * @param userId
     * @return
     */
    @Override
    public void addCart(Long skuId, Integer num, String userId) {
        //参数判断
        if (skuId == null || num == null || StringUtils.isEmpty(userId)){
            throw new RuntimeException("参数错误");
        }
        //查询购物车的数据
        List<CartInfo> cartInfoList = cartInfoMapper.selectList(new LambdaQueryWrapper<CartInfo>().eq(CartInfo::getUserId, userId));
        //判断是否为临时用户新增购物车
        if (cartInfoList.isEmpty()){
            CartInfo cartInfo = buildCartInfo(skuId, num,userId);
            //数据库新增
            cartAsyncService.add(cartInfo);
            //redis新增
            redisDataUpdate(cartInfo);
        }else {
            //修改购物车商品,进行累加
            for (CartInfo cartInfo : cartInfoList) {
                //判断当前的商品数据是否已经在购物车中
                if (cartInfo.getSkuId().equals(skuId)){
                    //进行数量的累加
                    cartInfo.setSkuNum(cartInfo.getSkuNum() + num);
                    //更新数据库
                    cartAsyncService.update(cartInfo);
                    //更新redis中的数据
                    redisDataUpdate(cartInfo);
                    //结束循环
                    break;
                }
            }
        }
    }

    /**
     * 临时用户新增购物车
     *
     * @param skuId
     * @param num
     * @param userId
     */
    @Override
    public String addCartTemp(Long skuId, Integer num, String userId) {
        //参数判断
        if (skuId == null || num == null){
            throw new RuntimeException("参数错误");
        }
        //判断临时用户是否为空
        if (StringUtils.isEmpty(userId)){
            //新增购物车
            userId = UUID.randomUUID().toString().replace("-","");
            //新增--购物车中没有这个商品
            CartInfo cartInfo = buildCartInfo(skuId,num,userId);
            //新增购物车数据--临时用户
            redisDataUpdate(cartInfo);
        }else {
            //修改购物车
            String cartInfoString = (String)stringRedisTemplate.boundHashOps(userId).get(RedisConst.SKUKEY_PREFIX + skuId);
            if (!StringUtils.isEmpty(cartInfoString)){
                //累加数据
                CartInfo cartInfo = JSONObject.parseObject(cartInfoString, CartInfo.class);
                cartInfo.setSkuNum(cartInfo.getSkuNum() + num);
                redisDataUpdate(cartInfo);
            }else {
                //直接添加
                CartInfo cartInfo = buildCartInfo(skuId,num,userId);
                redisDataUpdate(cartInfo);
            }
        }
        return  userId;
    }

    /**
     * 删除购物车数据
     *
     * @param userId
     * @param skuId
     */
    @Override
    public void deleteCart(Long userId, Long skuId) {
        //删除数据库的数据
        cartInfoMapper.delete(new LambdaQueryWrapper<CartInfo>().eq(CartInfo::getUserId ,userId)
                .eq(CartInfo::getSkuId, skuId));
        //删除redis的数据
        stringRedisTemplate.boundHashOps(userId + "").delete(RedisConst.SKUKEY_PREFIX + skuId);
    }

    /**
     * 修改购物车的数据
     *
     * @param skuId
     * @param num
     * @return
     */
    @Override
    public void updateCartInfo(Long skuId, Integer num,String userId) {
        //新增
        CartInfo cartInfo = buildCartInfo(skuId, num,userId);
        if (!StringUtils.isEmpty(userId)){
            //删除购物车的数据
            cartInfoMapper.delete(new LambdaQueryWrapper<CartInfo>().eq(CartInfo::getUserId ,userId)
                    .eq(CartInfo::getSkuId, skuId));
            //数据库新增
            cartAsyncService.add(cartInfo);
            //redis新增
            redisDataUpdate(cartInfo);
        }else {

            //redis新增
            redisDataUpdate(cartInfo);
        }

    }

    /**
     * 查询用户选中的购物车信息
     *
     * @param userId
     * @return
     */
    @Override
    public List<CartInfo> getChooseCartInfoList(Long userId) {
        return cartInfoMapper.selectList(
                new LambdaQueryWrapper<CartInfo>().eq(CartInfo::getUserId,userId)
                .eq(CartInfo::getIsChecked,1)
        );
    }


    /**
     * 查询购物车信息
     *
     * @param userId
     * @param tempUserId
     * @return
     */
    @Override
    public List<CartInfo> getCartInfoList(String userId, String tempUserId) {
        //参数校验一：都为空
        if (StringUtils.isEmpty(userId) && StringUtils.isEmpty(tempUserId)){
            return null;
        }
        //参数校验二：临时用户有值
        if (StringUtils.isEmpty(userId) && !StringUtils.isEmpty(tempUserId)){
            List<Object> values = stringRedisTemplate.boundHashOps(tempUserId).values();
            return values.stream().map(c ->{
                CartInfo cartInfo = JSONObject.parseObject(c.toString(), CartInfo.class);
                return cartInfo;
            }).collect(Collectors.toList());
        }
        //判断userId是否为空，不为空查询登录用户购物车数据-购物车1
        List<CartInfo> userCartList = new ArrayList<>();
        if (!StringUtils.isEmpty(userId)){
            //查询redis的购物车数据
            List<Object> values = stringRedisTemplate.boundHashOps(userId).values();
            //redis没有值则查询数据库,存入redis
            if (values.isEmpty()){
                userCartList = cartInfoMapper.selectList(
                        new LambdaQueryWrapper<CartInfo>().eq(CartInfo::getUserId,userId));
                if (!userCartList.isEmpty()){
                    //缓存到redis中
                    for (CartInfo cartInfo : userCartList) {
                        stringRedisTemplate.boundHashOps(userId).put(RedisConst.SKUKEY_PREFIX + cartInfo.getSkuId(),
                                JSONObject.toJSONString(cartInfo));
                    }
                }
            }else {
                userCartList = values.stream().map(c->{
                    CartInfo cartInfo = JSONObject.parseObject(c.toString(), CartInfo.class);
                    return cartInfo;
                }).collect(Collectors.toList());
            }
        }
        //判断临时userId是否为空，不为空查询临时用的数据库--购物车2
        List<CartInfo> tempUserLCartList = new ArrayList<>();
        if (!StringUtils.isEmpty(tempUserId)){
            //查询redis购物车数据
            List<Object> values = stringRedisTemplate.boundHashOps(tempUserId).values();
            if (!values.isEmpty()){
                tempUserLCartList = values.stream().map(c->{
                    CartInfo cartInfo = JSONObject.parseObject(c.toString(), CartInfo.class);
                    return cartInfo;
                }).collect(Collectors.toList());
            }
        }
        //如果购物车1和购物车2都不为空--合并--删除临时用户的购物车数据2
        if (!userCartList.isEmpty() && !tempUserLCartList.isEmpty()){
            //两个都不为空
            for (CartInfo cartInfo : tempUserLCartList) {
                CartInfo info = cartInfoMapper.selectOne(new LambdaQueryWrapper<CartInfo>()
                        .eq(CartInfo::getSkuId, cartInfo.getSkuId())
                        .eq(CartInfo::getUserId, userId));
                if (info != null){
                    //数量合并
                    info.setSkuNum(cartInfo.getSkuNum() + info.getSkuNum());
                    //存入数据库
                    cartInfoMapper.updateById(info);
                }else {
                    cartInfo.setUserId(userId);
                    cartInfoMapper.insert(cartInfo);
                }
                //删除redis中的当前购车数据
                stringRedisTemplate.boundHashOps(tempUserId).delete(RedisConst.SKUKEY_PREFIX + cartInfo.getSkuId());
            }
            //清楚当前所有的旧的登陆用户的购物车数据
            stringRedisTemplate.delete(userId);
            //当前合并的结果返回
            return cartInfoMapper.selectList(new LambdaQueryWrapper<CartInfo>().eq(CartInfo::getUserId,userId));
        }else if (tempUserLCartList.isEmpty() && !userCartList.isEmpty()){
            //临时用户的购物车为空,登录用户的购物车有值
            return userCartList;
        }else if (!tempUserLCartList.isEmpty() && userCartList.isEmpty()){
            //临时用户的购物车有值,登录用户的购物车为空
            //将临时用的购物车数据insert到数据库--删除临时用户的购物车数据
            for (CartInfo cartInfo : tempUserLCartList) {
                cartInfo.setUserId(userId);
                cartInfoMapper.insert(cartInfo);
            }
            stringRedisTemplate.delete(tempUserId);
            return tempUserLCartList;
        }
        //返回数据
        return null;
    }


    /**
     * 构建购物车对象实体
     * @param userId
     * @param skuId
     * @param num
     * @return
     */
    public CartInfo buildCartInfo(Long skuId,Integer num,String userId){
        //新增购物车中没有这个商品
        CartInfo cartInfo = new CartInfo();
        cartInfo.setUserId(userId);
        cartInfo.setSkuId(skuId);
        CompletableFuture<BigDecimal> skuPriceFuture = CompletableFuture.supplyAsync(new Supplier<BigDecimal>() {
            @Override
            public BigDecimal get() {
                BigDecimal skuPrice = productFeignClient.getSkuPrice(skuId);
                return skuPrice;
            }
        }, threadPoolExecutor);
        CompletableFuture<SkuInfo> skuInfoFuture = CompletableFuture.supplyAsync(new Supplier<SkuInfo>() {
            @Override
            public SkuInfo get() {
                SkuInfo skuInfo = productFeignClient.getSkuInfo(skuId);
                return skuInfo;
            }
        }, threadPoolExecutor);
        CompletableFuture.allOf(skuPriceFuture,skuInfoFuture).join();
        cartInfo.setSkuPrice(skuPriceFuture.join());
        cartInfo.setSkuNum(num);
        cartInfo.setImgUrl(skuInfoFuture.join().getSkuDefaultImg());
        cartInfo.setSkuName(skuInfoFuture.join().getSkuName());
        cartInfo.setIsChecked(1);
        //返回结果
        return cartInfo;
    }

    /**
     * 更新redis的数据
     * @param cartInfo
     */
    public void redisDataUpdate(CartInfo cartInfo){
        stringRedisTemplate.boundHashOps(cartInfo.getUserId()).put(RedisConst.SKUKEY_PREFIX + cartInfo.getSkuId(),
                JSONObject.toJSONString(cartInfo));
    }

}
